/*
 * @(#)GFERandom.java    1.0
 *
 * Copyright 2009 GFE, All rights reserved.
 * Game For Education.
 */
package egfe.utils;

import java.util.Random;

/**
 * @author  Sajarwo Anggai
 * @author  Abdul Rizal Adompo
 * @version 1.0, 11 May 2009
 * @see	    Random
 * @see	    GFEInfo
 */
public class GFERandom {

    /**
     * Element tidak ada yang duplikat
     */
    public static final int MODE1 = 0;
    /**
     * Element boleh ada yang duplikat
     */
    public static final int MODE2 = 1;
    /**
     * Element boleh diplikat dengan syarat ada batasan duplikatnya
     */
    public static final int MODE3 = 2;
    public static Random r = new Random();
    private int source[];
    private int dest[];
    private int mode = MODE1;
    private int duplicate = 2;

    public GFERandom(int mode) {
        setMode(mode);
    }

    public GFERandom(int mode, int src, int dst) {
        setMode(mode);
        setSource(src);
        setDestination(dst);
    }

    /**
     *
     * @param num banyaknya array yang akan dirandom
     */
    public void setSource(int num) {
        this.source = new int[num];
    }

    /**
     *
     * @param num banyaknya jumlah yang dibutuhkan
     */
    public void setDestination(int num) {
        this.dest = new int[num];
        for (int i = 0; i < dest.length; i++) {
            dest[i] = Integer.MAX_VALUE;
        }
    }

    /**
     *
     * @return hasil dari array yang dirandom
     */
    public int[] getResult() {
        return dest;
    }

    /**
     *
     * @param mode MODE1 - tidak boleh duplikat\n
     *             MODE2 - boleh duplikat
     *             MODE3 - boleh duplikat dengan syarat nilai duplikat ditentukan
     */
    public void setMode(int mode) {
        if (mode >= 0 && mode <= 2) {
            this.mode = mode;
        } else {
            this.mode = MODE1;
        }
    }

    /**
     *
     * @param duplicate banyaknya kemungikan yang di duplikat
     *        bagian ini diset apabila MODE3 dipilih
     */
    public void setMaxDuplicate(int duplicate) {
        this.duplicate = duplicate;
    }

    /**
     *
     * @return mode random yang digunakan
     */
    public int getMode() {
        return mode;
    }

    private int randomNotDuplicate() {
        int acak = r.nextInt(source.length);
        for (int i = 0; i < dest.length; i++) {
            if (dest[i] == acak) {
                return randomNotDuplicate();
            }
        }
        return acak;
    }

    private int randomDuplicate() {
        int acak = r.nextInt(source.length);
        int count = 0;
        for (int i = 0; i < dest.length; i++) {
            if (dest[i] == acak) {
                count++;
                if (count >= duplicate) {
                    return randomNotDuplicate();
                }
            }
        }
        return acak;
    }

    /**
     * Melakukan pembangkitan bilangan acak sesuai dengan source, destination
     * dan mode yang ditentukan
     */
    public synchronized void rand() {
        try {
            int count = 0;
            while (true) {
                if (mode == MODE1) {
                    dest[count] = randomNotDuplicate();
                } else if (mode == MODE2) {
                    dest[count] = r.nextInt(source.length);
                } else {
                    dest[count] = randomDuplicate();
                }
                count++;
                if (count >= dest.length) {
                    break;
                }
            }
        } catch (Exception e) {
        }
    }

    /**
     * Membangkitkan bilangan 
     * @param next batas jumlah kemunculan
     * @return nilai bilangan acak
     */
    public static int randomInt(int next) {
        return r.nextInt(next);
    }

    /**
     * Mencetak hasil dari operasi pembangkitan bilangan acak
     */
    public void print() {
        for (int i = 0; i < dest.length; i++) {
            System.out.println(i + " Item = " + dest[i]);
        }
    }
}
